#pragma once

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/asio/signal_set.hpp>
#include <boost/system/error_code.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <unordered_map>
#include <boost/unordered_map.hpp>
// #include "socketbase.h"
#include "socket_session.h"

namespace Socket
{
class SocketSession;

class SocketServer : public SocketInterface
{
public:
    SocketServer(const std::string ipaddress, const unsigned short port, const unsigned short num_threads) noexcept;
    ~SocketServer() noexcept;

    bool Start();
    void Stop() noexcept;

    void ClientStopCallback(unsigned short port);
    void ClientReadCallback(std::string str_read);
    void SeverWrite(std::string &str_write, unsigned short &port);

    void OnConnectStatus(bool *isConnected, boost::system::error_code *ec) {};
    void ReadCallback(std::string *str_read, boost::system::error_code *ec) 
    {
        printf("SocketServer Read Callback() --> %s, %s\n", (*str_read).c_str(), ec->message().c_str());
    };
    void HandleWrite(std::size_t *length, boost::system::error_code *ec) 
    {
        printf("SocketServer Write Callback() --> %ld, %s\n", *length, ec->message().c_str());
    };
    bool WriteSome(std::string &str_write) {return true;};

private:
    void WorkerThreadCallback(boost::shared_ptr<boost::asio::io_service> ios) noexcept;
    void AcceptHandler(boost::shared_ptr<SocketSession> session, const boost::system::error_code &ec) noexcept;
    void AcceptNewConnection() noexcept;

    boost::shared_ptr<boost::asio::io_service> m_ios_acceptors_;
    boost::shared_ptr<boost::asio::io_service::work> m_ios_work_acceptors_;
    boost::shared_ptr<boost::asio::io_service> m_ios_executors_;
    boost::shared_ptr<boost::asio::io_service::work> m_ios_work_executors_;
    boost::thread_group m_executors_thread_group_;

    boost::asio::ip::tcp::endpoint m_endpoint_;
    boost::asio::ip::tcp::acceptor m_acceptor_;
    boost::asio::signal_set m_signals_;

    boost::shared_ptr<SocketSession> ptr_session_;
    boost::unordered_map<unsigned short, boost::shared_ptr<SocketSession>> bumtmp;


};
}// namespace Socket